/*
 * This file is part of JSTUN. 
 * 
 * Copyright (c) 2005 Thomas King <king@t-king.de> - All rights
 * reserved.
 * 
 * This software is licensed under either the GNU Public License (GPL),
 * or the Apache 2.0 license. Copies of both license agreements are
 * included in this distribution.
 */

package com.jstun.core.attribute;

import com.jstun.core.util.Utility;
import com.jstun.core.util.UtilityException;

/**
 * ip, address가 변경됐는지 체크하고
 * 변경되었다면 ip, address가 변경되었다는 
 * header값을 변경하는 클래스
 *
 */
public class ChangeRequest extends MessageAttribute {
   /* 
    *  0                   1                   2                   3
    *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    * |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 A B 0|
    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    */
	boolean changeIP = false;
	boolean changePort = false;
	
	/**
	 * default 생성자 클래스
	 */
	public ChangeRequest() {
		super(MessageAttribute.MessageAttributeType.ChangeRequest);
	}
	
	/**
	 * ip가 변경됐는지 반환
	 * @return
	 */
	public boolean isChangeIP() {
		return changeIP;
	}
	
	/**
	 * port가 변경됐는지 반환
	 * @return
	 */
	public boolean isChangePort() {
		return changePort;
	}
	
	/**
	 * ip 변경 true 설정
	 */
	public void setChangeIP() {
		changeIP = true;
	}
	
	/**
	 * port 변경 true 설정
	 */
	public void setChangePort() {
		changePort = true;
	}
	
	/**
	 * 변경된 주소 or 포트를
	 * byte[]변환하여 반환
	 */
	public byte[] getBytes() throws UtilityException {
		byte[] result = new byte[8];
		// MessageAttributeHeader type 추출 및 복사
		System.arraycopy(Utility.integerToTwoBytes(typeToInteger(type)), 0, result, 0, 2);
		// length 길이 추출 및 복사
		System.arraycopy(Utility.integerToTwoBytes(4), 0, result, 2, 2);
		
		// 조건에 맞는 변경된 헤더 변경(ip, port, ip && port)
		if (changeIP) result[7] = Utility.integerToOneByte(4);
		if (changePort) result[7] = Utility.integerToOneByte(2);
		if (changeIP && changePort) result[7] = Utility.integerToOneByte(6);
		return result;
	}
	
	/**
	 * 인자로 byte[]로 받아 상태값을 
	 * 추출하여 ip, port가 변경 되었는지
	 * ChanageRequest에 설정후 객체 반환
	 * @param data
	 * @return
	 * @throws MessageAttributeParsingException
	 */
	public static ChangeRequest parse(byte[] data) throws MessageAttributeParsingException {
		try {
			if (data.length < 4) {
				throw new MessageAttributeParsingException("Data array too short");
			}
			ChangeRequest cr = new ChangeRequest();
			int status = Utility.oneByteToInteger(data[3]);
			switch (status) {
			case 0: break;
			case 2: cr.setChangePort(); break;
			case 4: cr.setChangeIP(); break;
			case 6: cr.setChangeIP(); cr.setChangePort(); break;
			default: throw new MessageAttributeParsingException("Status parsing error"); 
			}
			return cr;
		} catch (UtilityException ue) {
			throw new MessageAttributeParsingException("Parsing error");
		}
	}
}
